package presentation.web;

import java.rmi.RemoteException ;

import java.text.SimpleDateFormat ;
import java.util.Map ;
import java.util.Vector ;

import jaxcent.HtmlButton ;
import jaxcent.HtmlForm ;
import jaxcent.HtmlPara ;
import jaxcent.HtmlTable ;
import jaxcent.HtmlTextArea ;
import jaxcent.Jaxception ;
import presentation.UIMember ;
import presentation.UIPost ;
import presentation.UIThread ;
import util.Log ;
import util.NotFoundException ;
import util.Subsystem ;
import domain.user.Privilege ;
import domain.user.UnpermittedActionException ;

/**
 * Page for viewing the content of a thread
 *
 */
public class ViewThreadPage extends MainPage
{

	private UIThread currentThread ;
	private HtmlPara threadName ;
	private HtmlTable posts ;

	private HtmlButton addPost;
	private HtmlTextArea messageText;
	private HtmlForm addingPost;
	private HtmlPara errorsPara;
	private HtmlPara noPosts;

	private UIPost editedPost = null;


	/**
	 * Instantiates a new view thread page.
	 */
	public ViewThreadPage()
	{
		super() ;

		try
		{
			Map<String, String> params = this.getPageParams() ;
			long threadId = Long.parseLong(params.get("thread")) ;
			this.currentThread = this.getForumLogic().getThread(threadId) ;
			this.threadName = new HtmlPara(this, "threadname") ;
			this.threadName.setInnerHTML("Topic: " + this.currentThread.getTopic()) ;
		}
		catch (Exception e)
		{
			Log.getLogger(Subsystem.PAGE_RENDER).fine(e.getClass().getName() + "occured during creating root thread page");
			this.navigateToErrorPage(e, null) ;
			return ;
		}

		try
		{
			this.noPosts = new HtmlPara(this,"noPosts");
			this.noPosts.setInnerHTML("");
			this.loadPosts(this.currentThread) ;
			this.createAddButton();
			this.messageText = new HtmlTextArea(this,"messageText");
			this.addingPost = new HtmlForm(this,"addingPost");
			this.errorsPara = new HtmlPara(this,"errorField");
			this.clearAll();
			this.createAddingButtons();
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, null);
		}
	}

	private void clearAll()
	{
		try
		{
			this.addingPost.hide();
			this.editedPost = null;
			this.errorsPara.setInnerHTML("");
			this.messageText.setValue("");
			if(this.getUser().isAllowed(Privilege.ADD_POST))
			{
				this.addPost.show();
			}
		}
		catch (Exception e)
		{
			Log.getLogger(Subsystem.PAGE_RENDER).fine(e.getClass().getName() + "occured during clearing page");
			this.navigateToErrorPage(e, null) ;
		}
	}

	private void createAddButton()
	{
	    try
		{
			this.addPost = new HtmlButton(this,"addPost"){
		        @SuppressWarnings("synthetic-access")
				@Override
				protected void onClick() {
		        	try
					{
						ViewThreadPage.this.addingPost.show();
						ViewThreadPage.this.errorsPara.setInnerHTML("");
						this.hide();
					}
					catch (Jaxception e)
					{
						Log.getLogger(Subsystem.PAGE_RENDER).fine(e.getClass().getName() + "occured during adding a post");
						ViewThreadPage.this.navigateToErrorPage(e, null) ;
					}
		        }
		    };
	    	this.addPost.hide();
			if(this.getUser().isAllowed(Privilege.ADD_POST))
			{
				this.addPost.show();
			}
		}
		catch (Exception e)
		{
			Log.getLogger(Subsystem.PAGE_RENDER).fine(e.getClass().getName() + "occured during creating add post button");
			this.navigateToErrorPage(e, null) ;
		}
	}

	private void createAddingButtons()
	{
		try
		{
			new HtmlButton(this,"cancel"){
		        @SuppressWarnings("synthetic-access")
				@Override
				protected void onClick() {
		        	ViewThreadPage.this.clearAll();
		        }
		    };
			new HtmlButton(this,"reset"){
		        @SuppressWarnings("synthetic-access")
				@Override
				protected void onClick() {
		        	try
					{
						ViewThreadPage.this.messageText.setValue("");
						ViewThreadPage.this.errorsPara.setInnerHTML("");
					}
					catch (Jaxception e)
					{
						Log.getLogger(Subsystem.PAGE_RENDER).fine(e.getClass().getName() + "occured during reseting message content");
						ViewThreadPage.this.navigateToErrorPage(e, null) ;
					}
		        }
		    };
			new HtmlButton(this,"ok"){
		        @SuppressWarnings("synthetic-access")
				@Override
				protected void onClick() {
		        	ViewThreadPage.this.okButtonHandler();
		        }
		    };
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, null);
		}
	}

	private String getAuthorDetails(final UIMember currMember)
	{
		return "Name: " + currMember.getFirstName() + " " + currMember.getLastName() + "<br>" +
		"Gender: " + currMember.getGender() + "<br>" +
		"Date of Birth: " + currMember.getDateOfBirth() + "<br>" +
		"Residence: " + currMember.getResidence() ;
	}

	private String getPostDetails(final String timeOfPost, final UIMember currMember)
	{
		return "Author: "+ currMember.getUsername() + " ,  Created: " + timeOfPost ;
	}

	private void loadPosts(final UIThread thread)
	{
		Vector<UIPost> tposts ;
		try
		{
			tposts = this.getForumLogic().getPosts(thread.getId()) ;
		}
		catch (RemoteException e)
		{
			tposts = new Vector<UIPost>() ;
			Log.getLogger(Subsystem.PAGE_RENDER).fine(e.getClass().getName() + "occured during loading posts");
			this.navigateToErrorPage(e, null);
		}
		catch (NotFoundException e)
		{
			tposts = new Vector<UIPost>() ;
			Log.getLogger(Subsystem.PAGE_RENDER).fine(e.getClass().getName() + "occured during loading posts");
			this.navigateToErrorPage("Couldn't find container thread", null);
		}
		catch (Exception e)
		{
			tposts = new Vector<UIPost>() ;
			this.navigateToErrorPage(e, null);
		}

		try
		{
			this.posts = new HtmlTable(this, "posts") ;
			this.posts.deleteAllRows() ;
			this.posts.setBorder(1) ;
			this.posts.setWidth("1200") ;

			if (tposts.isEmpty())
			{
				this.noPosts.setInnerHTML("No posts created yet");
				return;
			}
			for (UIPost post: tposts)
			{
				this.posts.insertRow(-1, this.makePostRow(post)) ;
				this.makeButtonTable(post) ;
			}
		}
		catch (Exception e)
		{
			Log.getLogger(Subsystem.PAGE_RENDER).fine(e.getClass().getName() + "occured during creating posts");
			this.navigateToErrorPage(e, null);
		}
	}

	private void makeButtonTable(final UIPost post)
	{
		try
		{
			HtmlTable buttons = new HtmlTable(this, "post" + post.getId()) ;
			buttons.deleteAllRows() ;
			Vector<String> buttonCommands = new Vector<String>() ;

			if ( (post.getWriterId()==this.getUser().getId()
				&& this.getUser().isAllowed(Privilege.EDIT_POST))
				|| this.getUser().isAllowed(Privilege.EDIT_ANY_POST)){
				buttonCommands.add("<button id=editPost" + post.getId()+ " type=\"button\" >Edit</button>") ;
			}
			// if the user can delete posts: show this button
			if (this.getUser().isAllowed(Privilege.DELETE_POST))
			{
				buttonCommands.add("<button id=deletePost" + post.getId()+ " type=\"button\" >Delete</button>") ;
			}
			for (String s: buttonCommands)
			{
				String[] trow = new String[1] ;
				trow[0] = s ;
				buttons.insertRow(-1, trow) ;
			}
			if (this.getUser().isAllowed(Privilege.DELETE_POST))
			{
				new HtmlButton(this, "deletePost" + post.getId()) {
					@SuppressWarnings("synthetic-access")
					@Override
					 protected void onClick()
					 {
						 	try
							{
								ViewThreadPage.this.getForumLogic().deletePost(ViewThreadPage.this.getUser().getId(), post.getId(), ViewThreadPage.this.currentThread.getId()) ;
								loadPosts(ViewThreadPage.this.currentThread);
							}
							catch (UnpermittedActionException e)
							{
								Log.getLogger(Subsystem.PAGE_RENDER).fine("user is not allowed to delete this post");
								ViewThreadPage.this.navigateToErrorPage("You are not allowed to delete this post", null);
							}
							catch (NotFoundException e)
							{
								Log.getLogger(Subsystem.PAGE_RENDER).fine("container thread of the deleted post was deleted");
								ViewThreadPage.this.navigateToErrorPage("Container thread of the post you deleted has been deleted", null);
							}
							catch (Exception e)
							{
								Log.getLogger(Subsystem.PAGE_RENDER).fine(e.getClass().getName() + " has occured during deleting a post");
								ViewThreadPage.this.navigateToErrorPage(e, null);
							}
					 }
				} ;
			}
			if ((post.getWriterId()==this.getUser().getId() && this.getUser().isAllowed(Privilege.EDIT_POST)) || this.getUser().isAllowed(Privilege.EDIT_ANY_POST))
			{
				new HtmlButton(this, "editPost" + post.getId()) {
					@SuppressWarnings("synthetic-access")
					@Override
					protected void onClick()
					{
						try
						{
							ViewThreadPage.this.addingPost.show();
							ViewThreadPage.this.messageText.setValue(post.getMessage());
							ViewThreadPage.this.editedPost = post;
							ViewThreadPage.this.addPost.hide();
						}
						catch (Exception e)
						{
							Log.getLogger(Subsystem.PAGE_RENDER).fine(e.getClass().getName() + " has occured during editing a post");
							ViewThreadPage.this.navigateToErrorPage(e, null);
						}
					}
				} ;
			}
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, null);
		}

	}

	private String[] makePostRow(final UIPost post)
	{
		String[] result = new String[4] ;

		try
		{
			SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy  kk:mm");
			String timeOfPost = df.format(post.getDate());
			long currMemberId = post.getWriterId();
			UIMember currMember = this.getForumLogic().getMemberById(currMemberId) ;
			result[0] = this.getAuthorDetails(currMember) ;
			result[1] = "<h6>" + this.getPostDetails(timeOfPost, currMember) + "</h6>" + convertToHtml(post.getMessage()) ;

			result[2] = "<table id=post" + post.getId() + "> <tr><tc>placeholder</tc></tr> </table>" ;
		}
		catch (Exception e)
		{
			Log.getLogger(Subsystem.PAGE_RENDER).fine(e.getClass().getName() + " has occured during loading a post");
			this.navigateToErrorPage(e, null);
		}
		return result ;
	}

	private void okButtonHandler()
	{
		try
		{
			String msg = this.messageText.getValue() ;
			if(msg==null || msg.equals(""))
			{
				this.errorsPara.setInnerHTML("please enter a message");
				return;
			}
			if (this.editedPost == null )
			{
				UIPost post = this.getForumLogic().addPost(this.currentThread.getId(), this.getUser().getId(), msg);
				Log.getLogger(Subsystem.PAGE_RENDER).finest("user " + this.getUser().getId() + " has added the post with id "+post.getId()) ;
			}
			else
			{
				this.getForumLogic().editPost(this.editedPost.getId(), this.getUser().getId(), msg);
				Log.getLogger(Subsystem.PAGE_RENDER).finest("user " + this.getUser().getId() + " has edited the post with id "+this.editedPost.getId()) ;
			}
			this.clearAll();
			loadPosts(this.currentThread);
			this.noPosts.setInnerHTML("");
		}
		catch (Exception e)
		{
			this.clearAll();
			Log.getLogger(Subsystem.PAGE_RENDER).fine(e.getClass().getName() + " has occured during adding/editing a post");
			this.navigateToErrorPage(e, null);
		}
	}

}
